package com.sk.ccflower.server.lib.dbUtils;

import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.log4j.Logger;

import com.sk.ccflower.lib.commonUtils.FileUtil;
import com.sk.ccflower.lib.define.Consts;

public class SQLRunner {

	private Logger log;

	private Connection con = null;

	public SQLRunner() {

		this.log = Logger.getLogger(getClass());
	}

	public void begin(Connection con, boolean autoCommitMode)
			throws SQLException {
		this.con = con;
		this.con.setAutoCommit(autoCommitMode);
	}

	public void closeRs(ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException ex) {
			}
		}
	}

	public void closeStmt(Statement stmt) {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException ex) {
			}
		}
	}

	/**
	 * ******************** 중요 ********************** 
	 * WrapPool 에서 얻은 컨넥션은 반드시 반납해야하고 직접 맺은 컨넥션은 반드시 닫아줘야 한다.
	 * 
	 * @return Connection
	 */
	public Connection end() {
		return this.con;
	}

	public void commit() throws SQLException {
		this.con.commit();
	}

	public void rollback() throws SQLException {
		this.con.rollback();
	}

	public void executeQuery(String query) throws SQLException {
		Statement stmt = null;
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}
		try {
			stmt = con.createStatement();
			stmt.execute(query);
			this.log.debug(query);
		} catch (SQLException ex) {
			this.log.error(query + "," + ex.toString(), ex);
			throw ex;
		} finally {
			this.closeStmt(stmt);
		}
	}

	public HashMap<String, Object> executeQuery(String query,
			ArrayList<Object> params, Class<?> returnCls,
			ArrayList<String> keyFieldNames) throws SQLException, Exception {
		if (!this.checkQuery(query, params)) {
			throw new SQLException("? 와 파라메터 수가 다릅니다.");
		}
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		PreparedStatement pstmt = null;
		ResultSet rs = null;
		ResultSetMetaData rsmd;

		String[] colNames;
		Field[] fields = returnCls.getFields();

		int colSize = 0;
		Object obj;
		String key = null;
		/*
		 * Object key = null;
		 */
		HashMap<String, Object> hash = new HashMap<String, Object>();

		try {
			// keyFieldName이 제대로 되었는지 여부 체크 및 해당 필드를 가져온다.
			// keyFieldName가 잘못 입력되었으면 Exception을 발생한다.
			//
			Field[] keyField = new Field[keyFieldNames.size()];
			for (int kfc = 0; kfc < keyFieldNames.size(); kfc++)
				keyField[kfc] = returnCls.getField(keyFieldNames.get(kfc));

			/*
			 * keyMemberName = keyMemberName.toUpperCase();
			 */

			pstmt = this.con.prepareStatement(query);

			if (params == null) {
				params = new ArrayList<Object>();
			}
			for (int i = 0; i < params.size(); i++) {
				pstmt.setObject(i + 1, params.get(i));
			}
			rs = pstmt.executeQuery();
			this.log.debug(query + "param=" + params.toString());

			rsmd = rs.getMetaData();

			colSize = rsmd.getColumnCount();
			colNames = new String[colSize];
			int colIdx = 0;
			for (int i = 1; i <= colSize; i++) {

				colNames[colIdx] = rsmd.getColumnLabel(i);
				colIdx++;
			}

			key = new String();
			while (rs.next()) {
				colIdx = 0;
				obj = returnCls.newInstance();
				for (int i = 1; i <= colSize; i++) {
					this.setClass(fields, obj, colNames[colIdx], rs
							.getObject(i));
					/*
					 * key = this.findKey( fields , obj , keyMemberName);
					 */

					colIdx++;
				}

				key = "";
				for (int kfc = 0; kfc < keyField.length; kfc++) {
					if (kfc == 0)
						key = keyField[kfc].get(obj).toString();
					else
						key = key + "|" + keyField[kfc].get(obj).toString();
				}

				if (key == null) {
					this.log.error("KEY is Null [" + query + "]");
					continue;
				}

				hash.put(key, obj);
			}

		} catch (SQLException ex) {
			this.log.error(query + "," + "code = " + ex.getErrorCode()
					+ ", msg = " + ex.toString(), ex);
			throw ex;
		} catch (Exception ex) {
			this.log.error(ex.toString(), ex);
			throw ex;
		} finally {
			this.closeRs(rs);
			this.closeStmt(pstmt);
		}
		return hash;
	}

	public Object executeQueryObj(String query, ArrayList<Object> params,
			Class<?> returnCls) throws SQLException, Exception {
		if (!this.checkQuery(query, params)) {
			throw new SQLException("? 와 파라메터 수가 다릅니다.");
		}
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		PreparedStatement pstmt = null;
		ResultSet rs = null;

		Object obj = null;
		Object value = null;
		try {

			pstmt = this.con.prepareStatement(query);

			for (int i = 0; i < params.size(); i++) {
				pstmt.setObject(i + 1, params.get(i));
			}
			rs = pstmt.executeQuery();
			this.log.debug(query + "param=[" + params.toString() + "]");

			while (rs.next()) {
				obj = rs.getObject(1);
				if (obj instanceof BigDecimal) {
					if (returnCls.getSimpleName().equals("Integer")) {
						value = new Integer(((BigDecimal) obj).intValue());
					} else if (returnCls.getSimpleName().equals("Long")) {
						value = new Long(((BigDecimal) obj).longValue());
					} else if (returnCls.getSimpleName().equals("Double")) {
						value = new Double(((BigDecimal) obj).longValue());
					} else if (returnCls.getSimpleName().equals("Float")) {
						value = new Float(((BigDecimal) obj).floatValue());
					}
				} else {
					value = obj;
				}
			}

		} catch (SQLException ex) {
			this.log.error(query + "," + "code = " + ex.getErrorCode()
					+ ", msg = " + ex.toString(), ex);
			throw ex;
		} catch (Exception ex) {
			this.log.error(ex.toString(), ex);
			throw ex;
		} finally {
			this.closeRs(rs);
			this.closeStmt(pstmt);
		}
		return value;
	}

	public ArrayList<Object> executeQuery(String query,
			ArrayList<Object> params, Class<?> returnCls) throws SQLException,
			Exception {
		if (!this.checkQuery(query, params)) {
			throw new SQLException("? 와 파라메터 수가 다릅니다.");
		}
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		PreparedStatement pstmt = null;
		ResultSet rs = null;
		ResultSetMetaData rsmd;

		String[] colNames;
		Field[] fields = returnCls.getFields();

		ArrayList<Object> lists = new ArrayList<Object>();

		int colSize = 0;
		Object obj;
		try {

			pstmt = this.con.prepareStatement(query);

			for (int i = 0; i < params.size(); i++) {
				pstmt.setObject(i + 1, params.get(i));
			}
			rs = pstmt.executeQuery();
			this.log.debug(query + "param=[" + params.toString() + "]");

			rsmd = rs.getMetaData();

			colSize = rsmd.getColumnCount();
			colNames = new String[colSize];
			int colIdx = 0;
			for (int i = 1; i <= colSize; i++) {

				colNames[colIdx] = rsmd.getColumnLabel(i);
				// this.log.debug( colNames[colIdx] );
				colIdx++;
			}

			while (rs.next()) {
				colIdx = 0;
				obj = returnCls.newInstance();
				for (int i = 1; i <= colSize; i++) {
					this.setClass(fields, obj, colNames[colIdx], rs
							.getObject(i));
					colIdx++;
				}
				lists.add(obj);

			}

		} catch (SQLException ex) {
			this.log.error(query + "," + "code = " + ex.getErrorCode()
					+ ", msg = " + ex.toString(), ex);
			throw ex;
		} catch (Exception ex) {
			this.log.error(ex.toString(), ex);
			throw ex;
		} finally {
			this.closeRs(rs);
			this.closeStmt(pstmt);
		}
		return lists;
	}

	public static void main(String[] args) {

		try {

		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

	public int executeInsertClob(String query, Object value, String path,
			String clobName, String clobQuery, ArrayList<Object> clobParam)
			throws SQLException {

		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		this.log.debug("QUERY=[" + query + "]");
		PreparedStatement pstmt = null, clobPstmt = null;
		String[] colNames = null;
		Field[] fields = value.getClass().getFields();
		String memberStr = "";
		int updateCnt = -1;

		try {
			pstmt = this.con.prepareStatement(query);

			colNames = this.getColumnNames(query);
			for (int i = 0; i < colNames.length; i++) {
				memberStr = colNames[i];
				for (int j = 0; j < fields.length; j++) {

					if (memberStr.equals(fields[j].getName().toUpperCase())) {
						if (clobName.equals(fields[j].getName())) {

						} else {
							// if(fields[j].get( value )==null) pstmt.setNull(
							// i+1, pmd.getParameterType(i+1));
							if (fields[j].get(value) == null)
								pstmt.setNull(i + 1, Types.NULL);
							else
								pstmt.setObject(i + 1, fields[j].get(value));
							break;

						}
					}
				}
			}
			updateCnt = pstmt.executeUpdate();
			this.log.debug(query + "value=[" + value.toString() + "]");
			System.out.println(query + "value=[" + value.toString() + "]");
			clobPstmt = this.con.prepareStatement(clobQuery);
			for (int i = 0; i < clobParam.size(); i++) {
				clobPstmt.setObject(i + 1, clobParam.get(i));
			}

			ResultSet rs = clobPstmt.executeQuery();
			String clobData = new FileUtil().readFile(path);
			Clob clob;

			if (rs.next()) {
				clob = rs.getClob(1);
				clob.setCharacterStream(0);
				Writer wr = clob.setCharacterStream(0);
				wr.write(clobData);
				wr.close();

			}

		} catch (SQLException e) {
			e.printStackTrace();
			this.log.error(query + "," + "code = " + e.getErrorCode()
					+ ", msg = " + e.toString(), e);
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			this.log.error(e.toString(), e);
		} finally {
			this.closeStmt(pstmt);
		}

		return 0;
	}

	public int executeInsertClobForBuff(String query, String _buff,
			Object value, String clobName, String clobQuery,
			ArrayList<Object> clobParam) throws SQLException {

		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		this.log.debug("QUERY=[" + query + "]");
		PreparedStatement pstmt = null, clobPstmt = null;
		String[] colNames = null;
		Field[] fields = value.getClass().getFields();
		String memberStr = "";
		int updateCnt = -1;

		try {
			pstmt = this.con.prepareStatement(query);

			colNames = this.getColumnNames(query);
			for (int i = 0; i < colNames.length; i++) {
				memberStr = colNames[i];
				for (int j = 0; j < fields.length; j++) {

					if (memberStr.equals(fields[j].getName().toUpperCase())) {
						if (clobName.equals(fields[j].getName())) {

						} else {
							// if(fields[j].get( value )==null) pstmt.setNull(
							// i+1, pmd.getParameterType(i+1));
							if (fields[j].get(value) == null)
								pstmt.setNull(i + 1, Types.NULL);
							else
								pstmt.setObject(i + 1, fields[j].get(value));
							break;

						}
					}
				}
			}
			updateCnt = pstmt.executeUpdate();
			this.log.debug(query + "value=[" + value.toString() + "]");
			System.out.println(query + "value=[" + value.toString() + "]");
			clobPstmt = this.con.prepareStatement(clobQuery);
			for (int i = 0; i < clobParam.size(); i++) {
				clobPstmt.setObject(i + 1, clobParam.get(i));
			}

			ResultSet rs = clobPstmt.executeQuery();
			// String clobData = new FileUtil().readFile(path);
			String clobData = _buff;
			Clob clob;

			if (rs.next()) {
				clob = rs.getClob(1);
				clob.setCharacterStream(0);
				Writer wr = clob.setCharacterStream(0);
				wr.write(clobData);
				wr.close();

			}

		} catch (SQLException e) {
			e.printStackTrace();
			this.log.error(query + "," + "code = " + e.getErrorCode()
					+ ", msg = " + e.toString(), e);
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			this.log.error(e.toString(), e);
		} finally {
			this.closeStmt(pstmt);
		}

		return 0;
	}

	/**
	 * Query에는 Insert 할 컬럼을 반드시 명시해야 한다.
	 * 
	 * @param query
	 *            String
	 * @param obj
	 *            Object
	 * @param colMap
	 *            HashMap 멤버와 디비컬럼 이름이 달라진 항목을 설정한다. 이름이 맞지 않는 경우만 넣으면 됨.
	 * @throws SQLException
	 */
	public int executeInsert(String query, Object value,
			HashMap<String, String> colMap) throws SQLException {
		// colMap ( Key : column , value : member name )
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		if (colMap == null)
			colMap = new HashMap<String, String>(0);

		this.log.debug("QUERY=[" + query + "]");

		int updateCnt = -1;

		PreparedStatement pstmt = null;
		String[] colNames = null;
		Field[] fields = value.getClass().getFields();
		String memberStr = "";
		try {
			pstmt = this.con.prepareStatement(query);

			colNames = this.getColumnNames(query);
			for (int i = 0; i < colNames.length; i++) {
				memberStr = (String) colMap.get(colNames[i]);
				if (memberStr == null)
					memberStr = colNames[i];
				for (int j = 0; j < fields.length; j++) {
					if (memberStr.equals(fields[j].getName().toUpperCase())) {

						// if(fields[j].get( value )==null) pstmt.setNull( i+1,
						// pmd.getParameterType(i+1));
						if (fields[j].get(value) == null)
							pstmt.setNull(i + 1, Types.NULL);
						else
							pstmt.setObject(i + 1, fields[j].get(value));
						break;
					}
				}
			}
			updateCnt = pstmt.executeUpdate();
			this.log.debug(query + "value=[" + value.toString() + "]");

		} catch (SQLException e) {
			this.log.error(query + "," + "code = " + e.getErrorCode()
					+ ", msg = " + e.toString(), e);
			throw e;
		} catch (Exception e) {
			this.log.error(e.toString(), e);
		} finally {
			this.closeStmt(pstmt);
		}
		return updateCnt;
	}

	/**
	 * 
	 * @param query
	 *            String
	 * @param params
	 *            ArrayList 업데이트 할 값이 null 이면 리스트에 null 을 그냥 add(null) 하면 된다.
	 * @return int
	 * @throws SQLException
	 */
	public int executeUpdate(String query, ArrayList<Object> params)
			throws SQLException {
		if (!this.checkQuery(query, params)) {
			throw new SQLException("? 와 파라메터 수가 다릅니다.");
		}

		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		PreparedStatement pstmt = null;
		int updateCnt = -1;
		Object value = null;
		try {
			pstmt = this.con.prepareStatement(query);

			for (int i = 0; i < params.size(); i++) {
				value = params.get(i);
				if (value == null)
					pstmt.setNull(i + 1, Types.NULL);
				else
					pstmt.setObject(i + 1, params.get(i));
			}
			updateCnt = pstmt.executeUpdate();
			this.log.debug(query + "value=[" + params.toString() + "]");
		} catch (SQLException e) {
			this.log.error(query + "," + "code = " + e.getErrorCode()
					+ ", msg = " + e.toString(), e);
			throw e;
		} catch (Exception e) {
			this.log.error(e.toString(), e);
		} finally {
			this.closeStmt(pstmt);
		}

		return updateCnt;
	}

	public void executeUpdateBatch(String query,
			ArrayList<ArrayList<Object>> paramArrays, boolean _ignoreError)
			throws SQLException {
		ArrayList<Object> params = null;
		int d = paramArrays.size();

		while (d-- > 0) {
			params = (ArrayList<Object>) paramArrays.get(d);

			if (!this.checkQuery(query, params)) {
				throw new SQLException("? 와 파라메터 수가 다릅니다. index=" + d);
			}
		}

		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		if (params.size() < Consts.DB_BATCH_MAX_CNT) {
			this.executeUpdateBatchUnit(query, paramArrays, 0, paramArrays
					.size(), _ignoreError);
		} else {
			int startIdx = 0;
			int endIdx = 0;
			int size = (params.size() / Consts.DB_BATCH_MAX_CNT) + 1;
			for (int i = 0; i < size; i++) {
				startIdx = (i * Consts.DB_BATCH_MAX_CNT);
				endIdx = startIdx + Consts.DB_BATCH_MAX_CNT;
				if (i == (size - 1)) {
					endIdx = startIdx
							+ (params.size() % Consts.DB_BATCH_MAX_CNT);
				}

				try {
					this.executeUpdateBatchUnit(query, paramArrays, startIdx,
							endIdx, _ignoreError);
				} catch (SQLException e) {
					this.log.error(query + "," + "code = " + e.getErrorCode()
							+ ", msg = " + e.toString(), e);

					if (_ignoreError == false)
						throw e;
				}
			}
		}
	}

	/**
	 * 
	 * @param query
	 *            Update Query
	 * @param datas
	 * @param cls
	 * @param _aParamNames
	 *            파라메터 컬럼명 리스트
	 * @param colMap
	 * @throws SQLException
	 */
	private void executeUpdateBatchUnit(String query,
			ArrayList<ArrayList<Object>> paramArrays, int _startIdx,
			int _endIdx, boolean _ignoreError) throws SQLException {
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		PreparedStatement pstmt = null;

		try {
			//
			//
			pstmt = this.con.prepareStatement(query);

			//
			//
			ArrayList<Object> params = null;
			int j = 0;
			int nParams = 0;

			for (int i = _startIdx; i < _endIdx; i++) {
				try {
					params = (ArrayList<Object>) paramArrays.get(i);
					nParams = params.size();
					for (j = 0; j < nParams; j++) {
						if (params.get(j) == null)
							pstmt.setNull(j + 1, Types.NULL);
						else
							pstmt.setObject(j + 1, params.get(j));
					}
					pstmt.addBatch();
				} catch (SQLException e) {
					this.log.error("code = " + e.getErrorCode() + ", msg = "
							+ e.toString(), e);
					if (_ignoreError == false)
						throw e;
				}
			}
			pstmt.executeBatch();
			this.log.debug(query + "value=[" + params.toString() + "]");
		} catch (SQLException e) {
			this.log.error(query + "," + "code = " + e.getErrorCode()
					+ ", msg = " + e.toString(), e);
			throw e;
		} catch (Exception e) {
			this.log.error(e.toString(), e);
		} finally {
			this.closeStmt(pstmt);
		}
	}

	public int executeDelete(String query, ArrayList<Object> params)
			throws SQLException {
		return this.executeUpdate(query, params);
	}

	public void executeDeleteBatch(String query,
			ArrayList<ArrayList<Object>> paramArrays, boolean _ignoreError)
			throws SQLException {
		executeUpdateBatch(query, paramArrays, _ignoreError);
	}

	public void executeInsertBatch(String query, ArrayList<Object> datas,
			Class<?> cls, HashMap<String, String> colMap, boolean _ignoreError)
			throws SQLException {

		if (datas.size() < Consts.DB_BATCH_MAX_CNT) {
			this
					.executeInsertBatchUnit(query, datas, cls, colMap,
							_ignoreError);
		} else {
			int startIdx = 0;
			int endIdx = 0;
			int size = (datas.size() / Consts.DB_BATCH_MAX_CNT) + 1;
			for (int i = 0; i < size; i++) {
				startIdx = (i * Consts.DB_BATCH_MAX_CNT);
				endIdx = startIdx + Consts.DB_BATCH_MAX_CNT;
				if (i == (size - 1)) {
					endIdx = startIdx
							+ (datas.size() % Consts.DB_BATCH_MAX_CNT);
				}

				try {
					this.executeInsertBatchUnit(query, this.copySubList(datas,
							startIdx, endIdx), cls, colMap, _ignoreError);
				} catch (SQLException e) {
					this.log.error(query + "," + "code = " + e.getErrorCode()
							+ ", msg = " + e.toString(), e);
					if (_ignoreError == false)
						throw e;
				}
			}
		}
	}

	private ArrayList<Object> copySubList(ArrayList<Object> source,
			int startIdx, int endIdx) {
		int size = endIdx - startIdx;
		ArrayList<Object> list = new ArrayList<Object>(size);
		for (int i = startIdx; i < endIdx; i++) {
			list.add(source.get(i));
		}
		return list;

	}

	private void executeInsertBatchUnit(String query, ArrayList<Object> datas,
			Class<?> cls, HashMap<String, String> colMap, boolean _ignoreError)
			throws SQLException {
		// colMap ( Key : column , value : member name )
		if (this.con == null) {
			throw new SQLRunnerError("begin()을 먼저 호출하세요");
		}

		if (colMap == null)
			colMap = new HashMap<String, String>(0);

		PreparedStatement pstmt = null;
		String[] colNames = null;
		Field[] fields = cls.getFields();
		String memberStr = "";
		Object obj = null;
		try {
			pstmt = this.con.prepareStatement(query);

			colNames = this.getColumnNames(query);
			for (int dataIdx = 0; dataIdx < datas.size(); dataIdx++) {
				try {
					obj = datas.get(dataIdx);
					for (int i = 0; i < colNames.length; i++) {
						memberStr = (String) colMap.get(colNames[i]);
						if (memberStr == null)
							memberStr = colNames[i];
						for (int j = 0; j < fields.length; j++) {
							if (memberStr.equals(fields[j].getName()
									.toUpperCase())) {
								if (fields[j].get(obj) == null)
									pstmt.setNull(i + 1, Types.NULL);
								else
									pstmt.setObject(i + 1, fields[j].get(obj));
								break;
							}
						}
					}
					pstmt.addBatch();
				} catch (SQLException e) {
					this.log.error(query + "," + "code = " + e.getErrorCode()
							+ ", msg = " + e.toString(), e);
					if (_ignoreError == false)
						throw e;
				}
			}
			pstmt.executeBatch();
			this.log.debug(query + " *batch*");
		} catch (SQLException e) {
			this.log.error(query + "," + "code = " + e.getErrorCode()
					+ ", msg = " + e.toString(), e);
			throw e;
		} catch (Exception e) {
			this.log.error(e.toString(), e);
		} finally {
			this.closeStmt(pstmt);
		}
		// return updateCnt;

	}

	/**
	 * Insert 시 쿼리의 인서트 컬럼명을 얻는다. 사용용도는 member 변수와 연결하기위함이다.
	 * 
	 * @param query
	 *            String
	 * @return String[]
	 */
	private String[] getColumnNames(String query) {
		String[] colNames = null;
		String colStr = query.toUpperCase();
		colStr = colStr.substring(colStr.indexOf("(") + 1, colStr.indexOf(")"));
		colNames = colStr.split(",");
		for (int i = 0; i < colNames.length; i++) {
			colNames[i] = colNames[i].trim();
		}
		return colNames;
	}

	private void setClass(Field[] fields, Object obj, String filedName,
			Object value) throws Exception {
		filedName = filedName.toUpperCase();
		for (int i = 0; i < fields.length; i++) {
			if (filedName.equals(fields[i].getName().toUpperCase())) {

				if ( fields[i].getType().isPrimitive()) {
					if ( value == null ) {
						
					} else if ( value instanceof BigDecimal ) {
						this.setTypeCaseValue( fields[i], obj, (BigDecimal) value );
					} else if ( value instanceof Number ) {
						this.setTypeCaseValue( fields[i], obj, (Number) value );
					} else {
						this.log.warn("ResultSet에 맞는 타입을 발견하지 못했습니다.");
					}
				} else {
					// this.log.debug("### record("+fields[i].getName()+") value is : "+value.getClass().getName());
					if (value instanceof java.sql.Date) {
						fields[i].set(obj, value);
					} else if ( value instanceof java.sql.Timestamp ) {
						fields[i].set(obj, value);
					} else {
						if( fields[i].getType().isInstance(filedName) ) { // fineName을 비교하는게아니라 스트링형인지만 판단하는것...
	                        fields[i].set( obj, value );
	                	}
					}
				}
				break;
			}
		}
	}
	
	private void setTypeCaseValue(Field field, Object obj, BigDecimal value) throws Exception {
		Type t = field.getGenericType();
		
		if (t.toString().equals("int")) {
			field.setInt(obj, value.intValue());
		} else if (t.toString().equals("long")) {
			field.setLong(obj, value.longValue());
		} else if (t.toString().equals("float")) {
			field.setFloat(obj, value.floatValue());
		} else if (t.toString().equals("double")) {
			field.setDouble(obj, value.doubleValue());
		}
	}
	
	private void setTypeCaseValue(Field field, Object obj, Number value) throws Exception {
		Type t = field.getGenericType();
		
		if (t.toString().equals("int")) {
			field.setInt(obj, value.intValue());
		} else if (t.toString().equals("long")) {
			field.setLong(obj, value.longValue());
		} else if (t.toString().equals("float")) {
			field.setFloat(obj, value.floatValue());
		} else if (t.toString().equals("double")) {
			field.setDouble(obj, value.doubleValue());
		}
	}
	
	/*
	 * private Object findKey( Field[] fields , Object obj , String keyName )
	 * throws Exception{ Object value=null; for( int i=0; i<fields.length; i++
	 * ){ if( keyName.equals( fields[i].getName().toUpperCase() ) ){
	 * value=fields[i].get( obj ); break; } } return value; }
	 */

	private boolean checkQuery(String query, ArrayList<Object> params) {
		if (params == null)
			params = new ArrayList<Object>(0);
		return this.getQuestCnt(query) == params.size();
	}

	private int getQuestCnt(String query) {
		int questCnt = 0;
		char c = '?';
		char[] temp = query.toCharArray();
		for (int i = 0; i < temp.length; i++) {
			if (temp[i] == c) {
				questCnt++;
			}
		}
		return questCnt;
	}

}
